<template>
  <div id="custom-table">
    <table 
      cellpadding="0" 
      ref="tableSelf"
      :style="{
        width: getTableWidth() + 'px',
        height: getTableHeight() + 'px',
        border: borderType === 'border-self' ? '1px solid #aaa' : 'none'
      }">
      <tbody>
        <tr
          v-for="(row, rIndex) in rows"
          :key="rIndex"
          :style="{height: row.height + 'px'}"
          :class="[rIndex === rows.length ? 'cu-last-row' : '', 'table-row']"
        >
          <td
            v-for="(cell, cIndex) in row.cells"
            :key="cIndex"
            :id="rIndex + '' + cIndex"
            :style="{
              width: rows[0].cells[cIndex].width + 'px', 
              backgroundColor: getTableRowBackground(cell, rIndex), 
              borderColor: cell.borderColor,
              borderWidth: cell.borderWidth + 'px',
              borderLeftStyle: (cell.borderColor && borderType != 'border-half' && borderType != 'border-self' && borderType != 'border-none') ? 'double' : '',
              borderTopStyle: (cell.borderColor &&  borderType != 'border-self' && borderType != 'border-none') ? 'double' : '',
            }"
            :class="['table-td', (rIndex ===0 && borderType==='border-half') ? 'border-show-top' : borderType,  cell.isSelected ? 'cu-td-bg-selected' : '']"
            :rowspan="cell.rowspan || 1"
            :colspan="cell.colspan || 1"
            v-show="cell.isShow !== false"
            @mousedown="handleTdMousedown(cell, rIndex+1, cIndex+1, $event)"
            @mouseup="handleTdMouseup(rIndex+1, cIndex+1, $event)"
            @mouseenter.prevent="handleTdMouseMove(rIndex+1, cIndex+1, $event)"
            @contextmenu.stop.prevent="(e) => handleShowTableMenu(e,cell,rIndex+1, cIndex+1)"
            @dblclick="handleCellEditorDblClick(rIndex, cIndex, $event)"

          >
            <div class="cu-td-bg" :class="[getActiveStyle(rIndex+1, cIndex+1, cell.rowspan, cell.colspan) ? 'actived' : '', ]">
              <div 
                class="cu-td-content" 
                :style="{
                  ...cell.fontStyleObject,
                  fontSize: cell.fontStyleObject.fontSize + 'px',
                }"
                :contenteditable="!isMove && cell.isEditor"
                @click.stop="handleCellEditorClick(rIndex, cIndex, $event)"
                @input="handleInput(cell, $event)"
                @blur="handleTableEditCellBlur(cell, $event)"
                :ref="`editor-${rIndex}-${cIndex}`"
                v-html="cell.innerHtml"
              ></div>
              <div v-if="cell.isMerge || cell.isJudgment" class="cell-icon-style">
                <my-icon v-show="cell.isMerge" type="icon-shuangseshujuhebing"/>
                <my-icon v-show="cell.isJudgment" type="icon-shuangsepanduan"/>
              </div>
              <div 
                :class="[rIndex === 0 ? 'cu-td-border-top': 'cu-td-border-top-none']"
              ></div>
              <div 
                class="cu-td-border-right" 
                @mousedown.stop="handleTdDragStart({rIndex, cIndex}, 'right', $event)"
              ></div>
              <div 
                class="cu-td-border-bottom" 
                @mousedown.stop="handleTdDragStart({rIndex, cIndex}, 'bottom', $event)"
              ></div>
              <div 
                :class="[cIndex === 0 ? 'cu-td-border-left' : 'cu-td-border-left-none']"
              ></div>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
    <transition name="el-zoom-in-top">
      <ContextMenu 
        :is-move="isMove" 
        @click="handleMenuClick" 
        :locationX="locationX" 
        :locationY="locationY" 
        v-if="contextMenuVisible"
      />
    </transition>
  </div>
</template>

<script>
import ContextMenu from './context-menu/ContextMenu';
import { TABLR_CONSTANT } from './config';
import _ from 'lodash';
import uuid from 'uuidjs';

let canvasClientRect = null
let customTableDom = null
let positionInterval = {}
let currentCell ={}
let oldX = 0
let oldY = 0
let dragIndex = {rIndex: 0, cIndex: 0}
let dragDirection = 'bottom'
let currentCellPoint = {
  rowIndex: 0,
  columnIndex: 0
}

export default {
  name: "CustomTable",
  props: {
    rowAndCellLength: {
      type: Array,
      default: () => [3,3]
    },

    borderType: {
      type: String,
      default: 'border-full'
    },

    stripe: {
      type: Boolean,
      default: false
    },

    tableMaxWidth: {
      type: Number,
    },

    cellInitWidth: {
      type: Number,
      default: 30
    }

  },

  data() {
    return {
      rows: [],
      startPosition: {
        rowIndex: 0,
        columnIndex: 0,
      },
      endPosition: {
        rowIndex: 0,
        columnIndex: 0,
      },
      currentPosition: {
        rowIndex: 0,
        columnIndex: 0,
      },
      isSelect: false,
      isMove: false,

      locationX: 0,
      locationY: 0,
      contextMenuVisible: false,

      isDrag: false
    };
  },

  components: {
    ContextMenu,
  },

  created() {
    this.rows = this.createTableInfo(this.rowAndCellLength)
  },

  mounted() {
    customTableDom = document.getElementById('custom-table')
    if(this.tableMaxWidth) {
      this.setTableMaxWidth()
    }
    if(document.getElementById('canvas-content')) {
      canvasClientRect = document.getElementById('canvas-content').getBoundingClientRect()
    }
    document.addEventListener('mouseup', (e) => {
      this.isDrag = false;
      dragIndex = {rIndex: 0, cIndex: 0}
      if (e.button != 0) {
        return null;
      }
    })
    document.addEventListener('contextmenu', () => {
      this.contextMenuVisible = false
    })

    document.addEventListener('click', () => {
      this.contextMenuVisible = false
    })

    document.addEventListener('mousemove', (ev) => {
      this.tableDragjudement(ev)
    })
  },

  watch: {
    rowAndCellLength: function(val) {
      this.rows = this.createTableInfo(val)
    }
  },
  methods: {
    setTableMaxWidth() {
      customTableDom.style.maxWidth = this.tableMaxWidth + 'px'
      customTableDom.addEventListener('scroll', function() {
        if(customTableDom.scrollLeft === 0) {
          // customTableDom.children[0].style.boxShadow = '5px 0 10px -5px #aaa'
        } else if(customTableDom.scrollLeft >0 && customTableDom.scrollLeft < customTableDom.clientHeight) {
          //sdfsdf
        } else if(customTableDom.scrollLeft === customTableDom.clientHeight) {
          // customTableDom.children[0].style.boxShadow = '0 0 10px rgb(0 0 0 / 12%)'
        }
      })
    },
    /**
     * @Description: 根据父组件传入配置创建组件所需的数据
     * @param {*}
     * @Date: 2021-08-04 15:21:05
     */
    createTableInfo(value) {
      const [rowNum, columnNum] = value
      const { cellInitWidth } = this
      let result = []
      for(let i = 0; i<rowNum; i++) {
        result[i] = {cells: [], height: TABLR_CONSTANT.TABLE_CELL_MIN_HEIGHT}
        for(let j = 0; j<columnNum; j++) {
          result[i].cells[j] = {
            rowspan: 1, 
            colspan: 1, 
            innerHtml: '', 
            tempInnerHtml: '',
            borderWidth: 1,
            backgroundColor:'#fff',
            fontStyleObject: {
              fontFamily: 'PingFang SC',
              fontWeight: "normal",
              fontSize: 12,
              color: '#2F354D',
              textAlign: 'left',
              fontStyle: 'normal',
              letterSpacing: 0,
              lineHeight: 2,
            },
          }
          if(i === 0) {
            result[i].cells[j].width = cellInitWidth
          }
        }
      }
      return result
    },

    /**
     * @Description: 计算单元格宽度
     * @param {*} tableClientRect
     * @Date: 2021-08-03 17:17:49
     */
    computedTableCellWidth(tableClientRect) {
      return Number.parseInt((canvasClientRect.right - tableClientRect.left) / this.rows.length)
    },

    /**
     * @Description: 组件拖拽逻辑
     * @param {*}
     * @Date: 2021-07-29 15:36:02
     */
    tableDragjudement(ev) {
      if(this.isDrag) {
        if(dragDirection === 'bottom') {
          const dragX = this.rows[dragIndex.rIndex].height + (ev.y - oldY)
          this.rows[dragIndex.rIndex].height = dragX >= TABLR_CONSTANT.TABLE_CELL_MIN_HEIGHT ? dragX : TABLR_CONSTANT.TABLE_CELL_MIN_HEIGHT
          oldY = ev.y
        } else {
          const dragY = this.rows[0].cells[dragIndex.cIndex].width + (ev.x - oldX)
          this.rows[0].cells[dragIndex.cIndex].width = dragY >= TABLR_CONSTANT.TABLE_CELL_MIN_WIDTH ? dragY : TABLR_CONSTANT.TABLE_CELL_MIN_WIDTH
          oldX = ev.x
          oldX = ev.x
        }
      }
    },

    /**
     * @Description: 拖拽优化
     * @param {*}
     * @Date: 2021-07-29 15:37:51
     */
    dragOptimize() {

    },

    /**
     * @Description: 斑马纹
     * @param {*}
     * @Date: 2021-07-09 19:11:19
     */
    getTableRowBackground(cell, index) {
      if(cell.backgroundColor.substr(1).toLocaleLowerCase().substr(1,1) != 'f') {
        return cell.backgroundColor
      } else {
        let color = ''
        if(this.stripe) {
          color = index % 2 === 0 ? '#dddddc' : '#fff'
        } else {
          color = cell.backgroundColor
        }
        return color
      }
    },

    /**
     * @Description: 
     * @param {*}
     * @Date: 2021-07-09 17:09:33
     */
    handleInput(cell, event) {
      cell.tempInnerHtml = event.target.innerHTML
    },

    /**
     * @Description: 失去焦点调用
     * @param {*}
     * @Date: 2021-08-03 15:45:56
     */
    handleTableEditCellBlur(cell, event) {
      cell.innerHtml = event.target.innerHTML
    },
    

    /**
     * @Description: 设置单元格字段
     * @param {*}
     * @Date: 2021-07-09 16:25:42
     */
    setCellInnerText(field, fieldName) {
      console.log('fieldName', fieldName);
      this.setStoreTableInfo(this.rows.map((row) => {
          row.cells = row.cells.map((cell) => {
            if(cell.isSelected) {
              cell.tempInnerHtml ? cell.tempInnerHtml += `${fieldName}<br/>` : cell.tempInnerHtml = `${fieldName}<br/>`
              cell.innerHtml = cell.tempInnerHtml
            }
            return cell
          })
          return row
        }))
    },

    /**
     * @Description: 设置单元格规则
     * @param {*}
     * @Date: 2021-07-09 16:27:55
     */
    setCellJudgment() {
      
    },

    /**
     * @Description: 获取单元格内的fields
     * @param {*}
     * @Date: 2021-07-28 15:30:55
     */
    getSelectCellFields() {
      let cellContent = ''
      this.rows.forEach(row => {
        row.cells.forEach(cell => {
          if(cell.isSelected) {
            cellContent = cell.innerHtml
          }
        })
      })
      return cellContent.match(/{.*?}/g)
    },

    /**
     * @Description: 获取单元格配置规则
     * @param {*}
     * @Date: 2021-07-28 15:38:14
     */
    getSelectCellJudgmentList() {
      let cellJudgmentList = ''
      this.rows.forEach(row => {
        row.cells.forEach(cell => {
          if(cell.isSelected) {
            cellJudgmentList = cell.judgmentList
          }
        })
      })
      return cellJudgmentList
    },

    /**
     * @Description: 点击选中单个单元格 setStoreTableInfo
     * @param {*}
     * @Date: 2021-07-06 15:01:50
     */
    handleCellEditorClick(rowIndex, columnIndex, e) {
      if(e.button != 0) {
        return null;
      }
      this.setStoreTableInfo(
        this.rows.map((row, rIndex) => {
          row.cells = row.cells.map((cell, cIndex) => {
          if(rowIndex === rIndex && columnIndex === cIndex) {
            if(cell.isSelected) {
              cell.isEditor = true
              cell.isSelected = false
            } else {
              cell.isEditor ? '' : cell.isSelected = true
            }
          } else {
            cell.isSelected = false
            cell.isEditor = false
          }
          return cell
        })
        return row
      }))
    },

    /**
     * @Description: 清除单元格状态
     * @param {*} statusType
     * @Date: 2021-07-23 15:32:20
     */
    clearTableCellStatus(statusType) {
      this.setStoreTableInfo(
        this.rows.map((row) => {
           row.cells = row.cells.map((cell) => {
            cell[statusType] = false
            return cell
          })
          return row
        })
      )
    },

    /**
     * @Description: 双击输入
     * @param {*}
     * @Date: 2021-07-06 15:02:53
     */
    handleCellEditorDblClick(rowIndex, columnIndex, e) {
      e.stopPropagation();
      this.setStoreTableInfo(
        this.rows.map((row, rIndex) => {
           row.cells = row.cells.map((cell, cIndex) => {
            if(rowIndex === rIndex && columnIndex === cIndex) {
              cell.isEditor = true
            } else {
              cell.isEditor = false
            }
            cell.isSelected = false
            return cell
          })
          return row
        })
      )
      this.$nextTick(() => {
        this.getFocus(this.$refs[`editor-${rowIndex}-${columnIndex}`][0])
      })
    },

    /**
     * @Description: 添加，删除merge标识
     * @param {*}
     * @Date: 2021-07-06 16:51:14
     */
    setMergeIdentification() {
      this.setStoreTableInfo(
        this.rows.map((row) => {
           row.cells = row.cells.map((cell) => {
            if(cell.isSelected) {
              cell.isMerge = !cell.isMerge
            }
            return cell
          })
          return row
        })
      )
    },

    /**
     * @Description: 添加，删除逻辑标识
     * @param {*}
     * @Date: 2021-07-06 16:51:14
     */
    setJudgmentIdentification(judgmentList=[]) {
      this.setStoreTableInfo(
        this.rows.map((row) => {
           row.cells = row.cells.map((cell) => {
            if(cell.isSelected) {
              cell.isJudgment = judgmentList.length ? true : false
              cell.judgmentList = judgmentList
            }
            return cell
          })
          return row
        })
      )
    },
    
    /**
     * @Description: 获取表格宽度
     * @param {*}
     * @Date: 2021-05-31 17:17:55
     */
    getTableWidth() {
      return this.rows[0].cells.reduce((total, cell) => {
        return total + cell.width
      }, 0)
    },

    /**
     * @Description: 获取表格高度
     * @param {*}
     * @Date: 2021-05-31 17:26:26
     */
    getTableHeight() {
      return this.rows.reduce((total, row) => {
        return total + row.height
      }, 0)
    },
    /**
     * @Description: 鼠标按下
     * @param {*}
     * @Date: 2021-05-21 10:47:06
     */
    handleTdMousedown(cell, rowIndex, columnIndex, e) {
      console.log("down", rowIndex, columnIndex);
      if (e.button != 0) {
        return null;
      }
      this.clearTableCellStatus('isSelected');
      this.initData();
      this.isSelect = true;
      this.setCurrentCellInfo(cell, rowIndex, columnIndex)
      this.startPosition = {
        rowIndex,
        columnIndex,
      };
    },

    /**
     * @Description: 鼠标抬起
     * @param {*}
     * @Date: 2021-05-21 10:47:16
     */
    handleTdMouseup(rowIndex, columnIndex, e) {
      if (e.button != 0) {
        return null;
      }
      console.log("up", rowIndex, columnIndex);
      this.isSelect = false;
      this.endPosition = {
        rowIndex,
        columnIndex,
      };
    },

    /**
     * @Description: 鼠标移动
     * @param {*} rowIndex
     * @param {*} columnIndex
     * @Date: 2021-05-21 14:51:37
     */
    handleTdMouseMove(rowIndex, columnIndex) {
      if (this.isSelect) {
        this.isMove = true
        this.currentPosition = {
          rowIndex,
          columnIndex,
        };
      }
    },

    /**
     * @Description: 渲染背景颜色
     * @param {*} rowIndex
     * @param {*} columnIndex
     * @Date: 2021-05-21 14:51:44
     */
    getActiveStyle(rowIndex, columnIndex) {
      const { startPosition, currentPosition, endPosition, isMove } = this;
      const tempMaxPointX = _.max([startPosition.columnIndex,currentPosition.columnIndex, endPosition.columnIndex])
      const tempMaxPointY = _.max([startPosition.rowIndex, currentPosition.rowIndex, endPosition.rowIndex])
      const tempMinPointX = _.min([startPosition.columnIndex,currentPosition.columnIndex])
      const tempMinPointY = _.min([startPosition.rowIndex, currentPosition.rowIndex])
      const { maxPointX, maxPointY, minPointX, minPointY } = this.getPositionInterval(tempMaxPointX, tempMaxPointY, tempMinPointX, tempMinPointY)
      if (
        isMove && 
        rowIndex >= minPointY &&
        columnIndex >= minPointX &&
        rowIndex <= maxPointY &&
        columnIndex <= maxPointX
      ) {
        return true;
      } else {
        return false;
      }
    },

    /**
     * @Description: 获取坐标区间
     * @param {*}
     * @Date: 2021-05-26 14:06:36
     */
    getPositionInterval(xMax, yMax, xMin, yMin) {
      let maxPointX = xMax;
      let maxPointY = yMax;
      let minPointX = xMin;
      let minPointY = yMin;
      this.rows.forEach((row, rIndex) => {
        if(rIndex <= (yMax-1) && rIndex >= (yMin - 1)) {
          row.cells.forEach((cell, cIndex) => {
            if(cIndex <= (xMax-1) && cIndex >= (xMin - 1)) {
              if(cell.mergeInterval && !_.isEmpty(cell.mergeInterval)) {
                if(cell.mergeInterval[0][0] > yMax) {
                  maxPointY = cell.mergeInterval[0][0]
                }
                if(cell.mergeInterval[0][1] > xMax) {
                  maxPointX = cell.mergeInterval[0][1]
                }
                if(cell.mergeInterval[1][0] < yMin) {
                  minPointY = cell.mergeInterval[1][0]
                }
                if(cell.mergeInterval[1][1] < xMin) {
                  minPointX = cell.mergeInterval[1][1]
                }
              }
            }
          })
        }
      })
      if(maxPointY != yMax || minPointX != xMin || maxPointX != xMax || minPointY != yMin) {
        return this.getPositionInterval(maxPointX, maxPointY, minPointX, minPointY)
      } else {
        positionInterval =  {
          maxPointX,
          maxPointY,
          minPointX,
          minPointY
        }
        return positionInterval
      }
    },

    /**
     * @Description: 初始化数据
     * @param {*}
     * @Date: 2021-05-21 14:51:55
     */
    initData() {
      this.currentPosition = {
        rowIndex: 0,
        columnIndex: 0,
      };
      this.endPosition = {
        rowIndex: 0,
        columnIndex: 0,
      };

      this.startPosition= {
        rowIndex: 0,
        columnIndex: 0,
      }
      this.isMove = false
      this.isSelect = false
    },

    /**
     * @Description: 拖拽开始
     * @param {*}
     * @Date: 2021-05-25 10:05:47
     */
    handleTdDragStart(point, type, ev) {
      oldX = ev.x
      oldY = ev.y
      this.isDrag = true
      dragIndex = point
      dragDirection = type
    },

    /**
     * @Description: 展示自定义菜单
     * @param {*}
     * @Date: 2021-05-25 14:26:43
     */
    handleShowTableMenu(e, cell, rIndex, cIndex) {
      this.$emit('contextMenu')
      this.contextMenuVisible = true
      this.locationX = e.clientX
      this.locationY = e.clientY + 5
      this.setCurrentCellInfo(cell, rIndex, cIndex)
      
    },

    /**
     * @Description: 设置当前单元格数据
     * @param {*} cell
     * @param {*} rIndex
     * @param {*} cIndex
     * @Date: 2021-06-09 14:03:01
     */
    setCurrentCellInfo(cell, rIndex, cIndex) {
      currentCell = _.cloneDeep(cell)
      currentCellPoint = {
        rowIndex: rIndex,
        columnIndex: cIndex
      }
    },

    /**
     * @Description: 点击右键菜单事件
     * @param {*}
     * @Date: 2021-05-25 16:03:58
     */
    handleMenuClick(key, value=0) {
      if(key === 'merge-td') { // 合并单元格
        this.mergeCell()
      } else if(key === 'split-td') { // 拆分
        this.splitCell()
      } else if(key === 'insert-top-row') { // 向上插入
        this.insertTopRow(value)
      } else if(key === 'insert-bottom-row') { // 向下插入
        this.insertBottomRow(value)
      } else if(key === 'insert-left-column') { // 向左插入
        this.insertLeftColumn(value)
      } else if(key === 'insert-right-column') { // 向右插入
        this.insertRightColumn(value)
      } else if(key === 'delete-row') { // 删除选中行
        this.deleteSelectRow()
      } else if(key === 'delete-column') { // 删除选中列
        this.deleteSelectColumn()
      }
      this.contextMenuVisible = false
      this.initData();
    },

    /**
     * @Description: 向上插入行
     * @param {*}
     * @Date: 2021-05-27 15:34:03
     */
    insertTopRow(cloneNum) {
      const { setCopyCellData, isMove } = this
      const copyIndex = isMove ? positionInterval.minPointY - 1 : currentCellPoint.rowIndex - 1
      const tempData =[...new Array(Number.parseInt(cloneNum)).keys()].map(() => {
        return setCopyCellData(_.cloneDeep(this.rows[copyIndex]), 'top')
      })
      this.editCopyCell(_.cloneDeep(this.rows[copyIndex]), cloneNum, 'top')
      this.rows.splice(copyIndex, 0 , ...tempData)
      this.computedTableCellMergeInterval()
    },

    /**
     * @Description: 设置单元格数据
     * @param {*} row
     * @Date: 2021-06-02 13:47:22
     */
    setCopyCellData(row, type) {
      let oldId = ''
      let newId = ''
      row.cells = row.cells.map((cell,index) => {
        cell = _.cloneDeep(cell)
        cell.rowspan = 1
        if(cell.id === oldId) {
          cell.id = newId
        }

        // 如果向上插入时，复制的为具有rowspan 属性的单元格则更新复制行的Id
        if(type === 'top' && cell.mergeInterval && !_.isEmpty(cell.mergeInterval) && cell.isShow !== false) {
          oldId = cell.id
          cell.id = newId = uuid.generate()
        }

        // 向下插入时，复制为合并单元格最后一行是，则更新id
        if(type === 'bottom' && cell.mergeInterval && !_.isEmpty(cell.mergeInterval) && cell.mergeInterval[1][1] === index + 1) {
          if(cell.mergeInterval[0][0] === currentCellPoint.rowIndex) {
            oldId = cell.id
            cell.id = newId = uuid.generate()
            cell.colspan = cell.mergeInterval[0][1] - cell.mergeInterval[1][1] + 1
            cell.isShow = true
          } else {
             cell.isShow = false
          }
        }
        return this.initTableCellData(cell)
      })
      return _.cloneDeep(row)
    },

    /**
     * @Description: 修改被复制单元格的mergeInterval
     * @param {*} row
     * @param {*} cloneNum
     * @Date: 2021-06-02 14:41:54
     */
    editCopyCell(row, cloneNum, type) {
      let needEditCopyCellPoints = []
      row.cells.forEach((cell, cIndex) => {
        // 如果复制的行元素中包含合并的单元格，并且改单元格为不具有rowspan属性
        if(type === 'top' && !_.isEmpty(cell.mergeInterval) && cell.isShow === false && cIndex === (cell.mergeInterval[1][1] - 1)) {
          // 为防止重复修改具有rowspan属性单元格的rowspan加此判断
          if(needEditCopyCellPoints[0] != cell.mergeInterval[1][0] || needEditCopyCellPoints[1] != cell.mergeInterval[1][1]) {
            needEditCopyCellPoints = cell.mergeInterval[1]
            this.rows[cell.mergeInterval[1][0] - 1].cells[cell.mergeInterval[1][1] - 1].rowspan += parseInt(cloneNum)
          }
        }
        if(type === 'bottom' && !_.isEmpty(cell.mergeInterval) && cIndex === (cell.mergeInterval[1][1] - 1) && cell.mergeInterval[0][0] !== currentCellPoint.rowIndex) {
          this.rows[cell.mergeInterval[1][0] - 1].cells[cell.mergeInterval[1][1] - 1].rowspan += parseInt(cloneNum)
        }
      })
    }, 

    /**
     * @Description: 计算表格单元格的MergeInterval
     * @param {*}
     * @Date: 2021-06-02 13:47:02
     */
    computedTableCellMergeInterval() {
      this.rows.forEach((row, rIndex) => {
        row.cells.forEach((cell, cIndex) => {
          if(cell.isShow !== false && cell.mergeInterval && !_.isEmpty(cell.mergeInterval)) {
            if(cell.mergeInterval[1][0] != (rIndex+1) || cell.mergeInterval[1][1] != (cIndex + 1) || cell.mergeInterval[0][0] != (cell.rowspan + rIndex) || cell.mergeInterval[0][1] != (cell.colspan + rIndex)) {
              this.setCellMergeInterval(cell.id, [[(rIndex+cell.rowspan), (cell.colspan + cIndex)],[rIndex+1, cIndex+1]])
            }
          }
        })
      })
    },

    /**
     * @Description: 设置单元格的mergeInterval
     * @param {*} id
     * @param {*} mergeInterval
     * @Date: 2021-05-28 17:05:24
     */
    setCellMergeInterval(id, mergeInterval) {
      console.log('setCellMergeInterval', mergeInterval, id)
      this.rows.forEach(row => {
        row.cells.forEach(cell => {
          if(cell.id === id) {
            cell.mergeInterval = mergeInterval
          }
        })
      })
    },

    /**
     * @Description: 初始化单元格数据
     * @param {
     *  rowspan: 1, 
        colspan: 1, 
        innerHtml: '', 
        tempInnerHtml: '',
        fieldValueHtml: '',
        judgmentList: [],
        backgroundColor: '#FFF',
        borderColor: '#AAA'
        borderWidth: 1,
        isSelected: false,
        isEditor: false,
        fontStyleObject: {
          fontFamily: 'PingFang SC',
          fontWeight: "normal",
          fontSize: 12,
          color: '#2F354D',
          textAlign: 'left',
          fontStyle: 'normal',
          letterSpacing: 0,
          lineHeight: 2,
        },
     * }
     * @Date: 2021-08-03 14:14:16
     */
    initTableCellData(cellData) {
      return _.cloneDeep({
        ...cellData,
        innerHtml: '', 
        tempInnerHtml: '',
        fieldValueHtml: '',
        judgmentList: [],
        backgroundColor: '#FFF',
        borderColor: '#AAA',
        borderWidth: 1,
        isSelected: false,
        isEditor: false,
        fontStyleObject: {
          fontFamily: 'PingFang SC',
          fontWeight: "normal",
          fontSize: 12,
          color: '#2F354D',
          textAlign: 'left',
          fontStyle: 'normal',
          letterSpacing: 0,
          lineHeight: 2,
        },
      })
    },

    /**
     * @Description: 向下插入行
     * @param {*} cloneNum
     * @Date: 2021-05-27 16:29:01
     */
    insertBottomRow(cloneNum) {
      const { setCopyCellData, isMove } = this
      const copyIndex = isMove ? positionInterval.minPointY - 1 : currentCellPoint.rowIndex - 1
      const tempData =[...new Array(Number.parseInt(cloneNum)).keys()].map(() => {
        return setCopyCellData(_.cloneDeep(this.rows[copyIndex]), 'bottom')
      })
      this.editCopyCell(_.cloneDeep(this.rows[copyIndex]), cloneNum, 'bottom')
      this.rows.splice(copyIndex+1, 0, ...tempData)
      this.computedTableCellMergeInterval()
    },

    /**
     * @Description: 向左插入列
     * @param {*}
     * @Date: 2021-05-27 16:30:34
     */
    insertLeftColumn(cloneNum) {
      const { isMove } = this
      const copyIndex = isMove ? positionInterval.minPointX - 1 : currentCellPoint.columnIndex - 1
      // const tableEffectiveDistance = canvasClientRect.right - this.$refs['tableSelf'].getBoundingClientRect().left
      // customTableDom.style.maxWidth = tableEffectiveDistance + 'px'
      this.setCopyCellLetfOrRightData(cloneNum, copyIndex, 'left')
      this.computedTableCellMergeInterval()
      
    },

    setCopyCellLetfOrRightData(cloneNum, copyIndex, type) {
      this.rows.forEach((row) => {
        let copyCell;
        row.cells.forEach((cell, cIndex) => {
          if(cIndex === copyIndex) {
            copyCell = _setCopyCellData.bind(this)(_.cloneDeep(cell), cloneNum, copyIndex)
          }
        })
        row.cells.splice(type === 'left' ? copyIndex : copyIndex + 1, 0, ...[...new Array(Number.parseInt(cloneNum)).keys()].map(() => {
          return _.cloneDeep(copyCell)
        }))
      })

      function _setCopyCellData(cell, cloneNum, copyIndex) {
        if(cell.mergeInterval && !_.isEmpty(cell.mergeInterval)) {
          if(copyIndex === cell.mergeInterval[1][1] - 1 || copyIndex === cell.mergeInterval[0][1] - 1) {
            cell = {
              width: TABLR_CONSTANT.TABLE_CELL_MIN_WIDTH,
              rowspan: 1,
              colspan: 1
            }
          } else {
            this.rows[cell.mergeInterval[1][0] - 1].cells[cell.mergeInterval[1][1] -1].colspan += cloneNum
          }
        }
        return this.initTableCellData(cell)
      }
    },

    /**
     * @Description: 向右插入列
     * @param {*}
     * @Date: 2021-05-27 16:31:05
     */
    insertRightColumn(cloneNum) {
      const { isMove } = this
      const copyIndex = isMove ? positionInterval.minPointX - 1 : currentCellPoint.columnIndex - 1
      // const tableEffectiveDistance = canvasClientRect.right - this.$refs['tableSelf'].getBoundingClientRect().left
      // customTableDom.style.maxWidth = tableEffectiveDistance + 'px'
      this.setCopyCellLetfOrRightData(cloneNum, copyIndex, 'right')
      this.computedTableCellMergeInterval()
    },

    /**
     * @Description: 删除选中行
     * @param {*}
     * @Date: 2021-05-27 16:31:15
     */
    deleteSelectRow() {
      let needDeleteRowIndex = []
      if(this.isMove) {
        needDeleteRowIndex = [positionInterval.minPointY-1, positionInterval.maxPointY-1]
      } else {
        if(currentCell.mergeInterval && !_.isEmpty(currentCell.mergeInterval)) {
          needDeleteRowIndex = [currentCell.mergeInterval[1][0] -1, currentCell.mergeInterval[0][0] -1]
        } else {
          needDeleteRowIndex = [currentCellPoint.rowIndex -1, currentCellPoint.rowIndex -1]
        }
      }

      if(needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1 === this.rows.length) {
        return null
      }
      this.setDeleteRowCellData(needDeleteRowIndex)
    },

    setDeleteRowCellData(needDeleteRowIndex) {
      let mergeIds = []
      const tempRows = this.rows.filter((row, rIndex) => {
        if(rIndex >= needDeleteRowIndex[0] && rIndex <= needDeleteRowIndex[1]) {
          row.cells.forEach((cell) => {
            // 当删除的行中包含有rowspan属性的行时
            if(cell.mergeInterval && !_.isEmpty(cell.mergeInterval) && !mergeIds.includes(cell.id)) {
              mergeIds.push(cell.id)
              // 被删除行在合并单元格之内
              if((cell.mergeInterval[1][0]-1) < needDeleteRowIndex[0] && (cell.mergeInterval[0][0]-1) >= needDeleteRowIndex[1]) {
                // this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1].rowspan -= (needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1)
                const tempCell = this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1]
                const oldRowspan = tempCell.rowspan
                const needDeleteRowspan = (needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1)
                const oldColspan = tempCell.colspan
                oldRowspan - needDeleteRowspan === 1 ? this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1] = {
                  rowspan: oldRowspan - needDeleteRowspan,
                  colspan: oldColspan,
                  width: tempCell.width,
                } :
                this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1] = {
                  ...this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1],
                  rowspan: oldRowspan - needDeleteRowspan,
                }
              } else if ((cell.mergeInterval[1][0]-1) < needDeleteRowIndex[0] && (cell.mergeInterval[0][0]-1) <= needDeleteRowIndex[1]) {
                const tempCell = this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1]
                const oldRowspan = tempCell.rowspan
                const needDeleteRowspan = (needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1)
                const oldColspan = tempCell.colspan
                oldRowspan - needDeleteRowspan === 1 ? this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1] = {
                  rowspan: oldRowspan - needDeleteRowspan,
                  colspan: oldColspan,
                  width: tempCell.width,
                } :
                this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1] = {
                  ...this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1],
                  rowspan: oldRowspan - needDeleteRowspan,
                }
              } else if((cell.mergeInterval[1][0]-1) >= needDeleteRowIndex[0] && (cell.mergeInterval[0][0]-1) > needDeleteRowIndex[1]) {
                this.rows[needDeleteRowIndex[1]+1].cells[cell.mergeInterval[1][1]-1] = {
                  ...this.rows[cell.mergeInterval[1][0] - 1].cells[cell.mergeInterval[1][1]-1],
                  isShow: true,
                  rowspan: (cell.mergeInterval[0][0] - 1 - needDeleteRowIndex[1])
                }
              }
            }
          })
        }
        return rIndex < needDeleteRowIndex[0] || rIndex > needDeleteRowIndex[1]
      })
      
      this.setStoreTableInfo(tempRows)
      
      this.$nextTick(() => {
        this.computedTableCellMergeInterval()
      })
    },

    /**
     * @Description: 设置vuex 中关于table组件的数据值
     * @param {*} id
     * @param {*} tableInfo
     * @Date: 2021-07-06 15:39:20
     */
    setStoreTableInfo(rows) {
      this.rows = rows
    },

    /**
     * @Description: 删除选中列
     * @param {*}
     * @Date: 2021-05-27 16:31:24
     */
    deleteSelectColumn() {
      let needDeleteRowIndex = []
      if(this.isMove) {
        needDeleteRowIndex = [positionInterval.minPointX, positionInterval.maxPointX]
      } else {
        if(currentCell.mergeInterval && !_.isEmpty(currentCell.mergeInterval)) {
          needDeleteRowIndex = [currentCell.mergeInterval[1][1], currentCell.mergeInterval[0][1]]
        } else {
          needDeleteRowIndex = [currentCellPoint.rowIndex, currentCellPoint.rowIndex]
        }
      }
      if(needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1 === this.rows[0].cells.length) {
        return null
      }
      this.setDeleteColumnCellData(needDeleteRowIndex)
    },

    setDeleteColumnCellData(needDeleteRowIndex) {
      let mergeIds = []
      this.rows.forEach((row) => {
        row.cells = row.cells.filter((cell, cIndex) => {
          if(cell.mergeInterval && !_.isEmpty(cell.mergeInterval) && !mergeIds.includes(cell.id)) {
            mergeIds.push(cell.id)
            if(cell.mergeInterval[1][1] < needDeleteRowIndex[0] && cell.mergeInterval[0][1] >= needDeleteRowIndex[1]) {
              const tempCell = this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1]
              tempCell.colspan - (needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1) === 1 ? this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1] = {
                colspan:  tempCell.colspan - (needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1),
                width: tempCell.width
              } : this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1] = {
                ...tempCell,
                colspan:  tempCell.colspan - (needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1),
              }
            }else if(cell.mergeInterval[1][1] >= needDeleteRowIndex[0] && cell.mergeInterval[0][1] > needDeleteRowIndex[1]) {
              this.rows[cell.mergeInterval[1][0]-1].cells[needDeleteRowIndex[1]] = {
                ...this.rows[cell.mergeInterval[1][0] -1].cells[cell.mergeInterval[1][1] -1],
                colspan: (cell.mergeInterval[0][1] - needDeleteRowIndex[1]),
                isShow: true
              }
            } else if(cell.mergeInterval[1][1] <= needDeleteRowIndex[0] && cell.mergeInterval[0][1] < needDeleteRowIndex[1]) {
              const tempCell = this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1]
              tempCell.colspan - (needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1) === 1 ? this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1] = {
                colspan:  tempCell.colspan - (needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1),
                width: tempCell.width
              } : this.rows[cell.mergeInterval[1][0]-1].cells[cell.mergeInterval[1][1]-1] = {
                ...tempCell,
                colspan:  tempCell.colspan - (needDeleteRowIndex[1] - needDeleteRowIndex[0] + 1),
              }
            }
          }
          return cIndex < (needDeleteRowIndex[0] -1) || cIndex > (needDeleteRowIndex[1] - 1)
        })
      })
      this.computedTableCellMergeInterval()
    },
    

    /**
     * @Description: 拆分单元格
     * @param {*}
     * @Date: 2021-05-26 19:40:35
     */
    splitCell() {
      this.computeSplitPoint();
    },
    computeSplitPoint() {
      if(_.isEmpty(currentCell.mergeInterval) || !currentCell.mergeInterval.length) {
        return
      }
      const [[maxPointY, maxPointX], [minPointY, minPointX]] = currentCell.mergeInterval
      return this.rows.map((row, rIndex) => {
        if(rIndex >= minPointY - 1 && rIndex <= maxPointY-1) {
          row.cells = row.cells.map((cell, cIndex) => {
            if(cIndex >= minPointX - 1 && cIndex <= maxPointX - 1) {
              cell.colspan = 1;
              cell.rowspan = 1;
              // cell.width = TABLR_CONSTANT.TABLE_CELL_MIN_WIDTH
              cell.isShow = true;
              cell.mergeInterval = null;
              cell.id = null;
            }
            return cell
          })
        }
        return row
      })
    },

    /**
     * @Description: 合并单元格
     * @param {*}
     * maxPointX,
        maxPointY,
        minPointX,
        minPointY
     * @Date: 2021-05-25 16:08:45
     */
    mergeCell() {
      this.computeMergePoint([positionInterval.maxPointY, positionInterval.maxPointX], [positionInterval.minPointY, positionInterval.minPointX])
    },

    computeMergePoint(maxPoint, minPoint) {
      const mergeId = uuid.generate()
      return this.rows.map((row,rIndex) => {
        if(rIndex === (minPoint[0] - 1)) {
          row.cells = row.cells.map((cell, cIndex) => {
            if(cIndex === (minPoint[1]-1)) {
              cell.colspan = (maxPoint[1] - minPoint[1]) + 1;
              cell.rowspan = (maxPoint[0] - minPoint[0]) + 1;
              // cell.width = cell.colspan * 30
              cell.mergeInterval = [maxPoint, minPoint]
              cell.id = mergeId
            } else if(cIndex > (minPoint[1]-1) && cIndex <= (maxPoint[1]-1)) {
              cell.isShow = false
              cell.colspan = 1;
              cell.rowspan = 1;
              cell.mergeInterval = [maxPoint, minPoint]
              cell.id = mergeId
            }
            return cell
          })
        } else if(rIndex > (minPoint[0] - 1) && rIndex <= (maxPoint[0] - 1)) {
          row.cells = row.cells.map((cell, cIndex) => {
            if(cIndex >= (minPoint[1]-1) && cIndex <= (maxPoint[1]-1)) {
              cell.colspan = 1;
              cell.rowspan = 1;
              cell.mergeInterval = [maxPoint, minPoint]
              cell.id = mergeId
              cell.isShow = false
            }
            return cell
          })
        }
        return row
      })
    },

    getTdWidth(id) {
      let width = 0
      this.$nextTick(() => {
         width = document.getElementById(id).parentElement.clientWidth
      })
      return width
    },

    /**
     * @Description: 重置选中区域单元格样式
     * @param {*}
     * @Date: 2021-08-05 15:42:54
     */
    initCellStyle() {
      if(this.isMove) {
        this.rows.forEach((row, rIndex) => {
          if(rIndex >= positionInterval.minPointY - 1 && rIndex <= positionInterval.maxPointY -1) {
            row.cells = row.cells.map((cell, cIndex) => {
              if(cIndex <= positionInterval.maxPointX - 1 && cIndex >= positionInterval.minPointX - 1) {
                cell = {
                  ...cell,
                  backgroundColor: '#FFF',
                  borderColor: '#AAA',
                  borderWidth: 1,
                  fontStyleObject: {
                    fontFamily: 'PingFang SC',
                    fontWeight: "normal",
                    fontSize: 12,
                    color: '#2F354D',
                    textAlign: 'left',
                    fontStyle: 'normal',
                    letterSpacing: 0,
                    lineHeight: 2,
                  },
                }
              }
              return cell
            })
          }
        })
        this.isMove = false
      } else {
        if(this.rows[currentCellPoint.rowIndex - 1]) {
          this.rows[currentCellPoint.rowIndex - 1].cells[currentCellPoint.columnIndex - 1] = {
            ...this.rows[currentCellPoint.rowIndex - 1].cells[currentCellPoint.columnIndex - 1],
            backgroundColor: '#FFF',
            borderColor: '#AAA',
            borderWidth: 1,
            fontStyleObject: {
              fontFamily: 'PingFang SC',
              fontWeight: "normal",
              fontSize: 12,
              color: '#2F354D',
              textAlign: 'left',
              fontStyle: 'normal',
              letterSpacing: 0,
              lineHeight: 2,
            },
          }
        }
      }
      this.$forceUpdate();
    },

    /**
     * @Description: 设置单元格样式
     * @param {*} styleName
     * @param {*} value
     * @Date: 2021-06-09 18:30:22
     */
    setCellCommonStyle(styleName, value) {
      if(this.isMove) {
        this.rows.forEach((row, rIndex) => {
          if(rIndex >= positionInterval.minPointY - 1 && rIndex <= positionInterval.maxPointY -1) {
            row.cells.forEach((cell, cIndex) => {
              if(cIndex <= positionInterval.maxPointX - 1 && cIndex >= positionInterval.minPointX - 1) {
                cell[styleName] = typeof cell[styleName] === 'object' ? {
                  ...cell[styleName],
                  ...value
                } : value
              }
            })
          }
        })
        this.isMove = false
      } else {
        if(this.rows[currentCellPoint.rowIndex - 1]) {
          const targetCellPropery = this.rows[currentCellPoint.rowIndex - 1].cells[currentCellPoint.columnIndex - 1][styleName]
           this.rows[currentCellPoint.rowIndex - 1].cells[currentCellPoint.columnIndex - 1][styleName] = typeof targetCellPropery === 'object' ? {
             ...targetCellPropery,
             ...value
           }:value
        }
      }
      this.$forceUpdate();
    },

    /**
     * @Description: 设置单元格背景色
     * @param {*} color
     * @Date: 2021-06-09 13:48:47
     */
    setCellBackgroundColor(color) {
      console.log('color', color)
      this.rows.forEach((row, rIndex) => {
        if(rIndex >= positionInterval.minPointY - 1 && rIndex <= positionInterval.maxPointY -1) {
          row.cells.forEach((cell, cIndex) => {
            if(cIndex <= positionInterval.maxPointX - 1 && cIndex >= positionInterval.minPointX - 1) {
              cell.backgroundColor = color
            }
          })
        }
      })
      this.isMove = false
      this.$forceUpdate();
    },

    /**
     * @Description: 设置单元格边框颜色
     * @param {*} color
     * @Date: 2021-06-09 14:37:51
     */
    setCellBorderColor(color) {
      if(this.isMove) {
        this.rows.forEach((row, rIndex) => {
          if(rIndex >= positionInterval.minPointY - 1 && rIndex <= positionInterval.maxPointY -1) {
            row.cells.forEach((cell, cIndex) => {
              if(cIndex <= positionInterval.maxPointX - 1 && cIndex >= positionInterval.minPointX - 1) {
                cell.borderColor = color
              }
            })
          }
        })
        this.isMove = false
      } else {
        this.rows[currentCellPoint.rowIndex + 1].cells[currentCellPoint.columnIndex + 1].borderColor = color
      }
      this.$forceUpdate();
    },

    /**
     * @Description: 设置单元格边框线宽度
     * @param {*} width
     * @Date: 2021-06-09 14:39:25
     */
    setCellBorderWidth(width) {
      this.rows.forEach((row, rIndex) => {
        if(rIndex >= positionInterval.minPointY - 1 && rIndex <= positionInterval.maxPointY -1) {
          row.cells.forEach((cell, cIndex) => {
            if(cIndex <= positionInterval.maxPointX - 1 && cIndex >= positionInterval.minPointX - 1) {
              cell.borderWidth = width
            }
          })
        }
      })
      this.isMove = false
      this.$forceUpdate();
    },

    /**
     * @Description: 设置字体样式
     * @param {*} styleObject
     * @Date: 2021-06-09 16:29:54
     */
    setCellFontStyle(fontStyleObject) {
      this.rows.forEach((row, rIndex) => {
        if(rIndex >= positionInterval.minPointY - 1 && rIndex <= positionInterval.maxPointY -1) {
          row.cells.forEach((cell, cIndex) => {
            if(cIndex <= positionInterval.maxPointX - 1 && cIndex >= positionInterval.minPointX - 1) {
              cell.fontStyleObject = fontStyleObject
            }
          })
        }
      })
      this.isMove = false
      this.$forceUpdate();
    },

    /**
     * @Description: 设置光标放置于文本末尾
     * @param {*}
     * @Date: 2021-06-21 17:14:03
     */
    getFocus(el) {
      el.focus();
      let range = document.createRange();
      range.selectNodeContents(el);
      range.collapse(false);
      let sel = window.getSelection();

      //判断光标位置，如不需要可删除
      if(sel.anchorOffset != 0){
          return true;
      }
      sel.removeAllRanges();
      sel.addRange(range);
    }
  },
};
</script>

<style lang="less" scoped>
@import url("./index.less");
#custom-table {
  overflow-x: auto;
  overflow-y: hidden;
  table {
    border-collapse: collapse;
    background-color: #fff;
    .cu-last-row {
      .table-td,td {
        .cu-td-bg {
          .cu-td-border-bottom {
            display: block;
            bottom: 0;
          }
        }
      }
    }
  }
}
</style>

<style lang="less" scoped>
  table {
    /deep/.ant-input {
      border: none;
      outline: none;
      box-shadow: none;
      border-radius: 0;
      padding: 0;
      margin: 0;
      height: 100%;
    }
  }
  // width: 100%;
</style>